/**
 * @filename:SysMenuController 2022年1月27日
 * @project Wonder xhadmin Framework  V1.0
 * Copyright(c) 2020 LuZhongren Co. Ltd. 
 * All right reserved. 
 */
package com.wonder.admin.controller;

import com.wonder.admin.constant.Parameters;
import com.wonder.admin.domain.SysAction;
import com.wonder.admin.domain.SysApplication;
import com.wonder.admin.domain.SysField;
import com.wonder.admin.domain.SysMenu;
import com.wonder.admin.service.SysActionService;
import com.wonder.admin.service.SysApplicationService;
import com.wonder.admin.service.SysFieldService;
import com.wonder.admin.service.SysMenuService;
import com.wonder.admin.tools.GeneratorService;
import com.wonder.admin.domain.I118;
import com.wonder.admin.service.I118Service;
import com.wonder.admin.request.SysMenuRequest;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wonder.common.common.AjaxMap;
import com.wonder.common.common.AjaxResult;
import com.wonder.common.config.WonderConfig;
import com.wonder.common.constants.Constants;
import com.wonder.common.exception.ExceptionCodeEnum;
import com.wonder.common.utils.MessageUtils;
import com.wonder.common.utils.StringUtils;
import com.wonder.common.utils.bean.BeanUtils;
import com.wonder.tools.model.ModuleInfo;


import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.java.Log;


/**
 * 
 * <p>
 * 说明： 菜单管理API接口层
 * </P>
 * 
 * @version: V1.0
 * @author: LuZhongren
 * @time 2022年1月27日
 *
 */
@Api(tags = "菜单管理")
@RestController
@CrossOrigin
@RequestMapping("/admin/Sys.Base")
@Log
public class SysMenuController {
	

	@Autowired
	private SysMenuService sysMenuService;

	@Autowired
	private SysApplicationService sysApplicationService;

	@Autowired
	private SysFieldService sysFieldService;

	@Autowired
	private SysActionService sysActionService;
	
	@Autowired
	private I118Service i118Service;
	
	@Value("${gen.tablePrefix}")
	private String tablePrefix;
	
	/**
	 * Link to the url for generate the source code
	 */
	@Value("${wonder.toolsUrl}")
	private String toolsUrl;

	@ApiOperation(value = "获取菜单列表")
	@RequestMapping(value = "/getMenuList", method = RequestMethod.POST)
	public Map<String, Object> getMenuList(@RequestBody SysMenuRequest sysMenuRequest) {
		Long app_id = sysMenuRequest.getApp_id().longValue();
		List<SysMenu> menus = sysMenuService
				.list(new QueryWrapper<SysMenu>().eq("app_id", app_id).orderByAsc("sortid"));
		List<SysMenu> menuTree = sysMenuService.buildMenuTree(menus);
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("list", menuTree);
		map.put("connects", new String[] { "master" });
		map.put("defaultConnect", "master");
		map.put("tableList", sysFieldService.getTableList());
		map.put("page_type_list", Parameters.page_type_list());
		List<Map<String, Object>> apps = sysApplicationService.listMaps(new QueryWrapper<SysApplication>()
				.eq("app_id", app_id).select("app_id", "app_type", "application_name"));

		for (Map<String, Object> item : apps) {
			Map<String, String> param = new HashMap<String, String>();
			param.put("app_id", app_id.toString());
			param.put("app_type", item.get("app_type").toString());
			item.put("url", "admin/Menu/index.html?" + asUrlParams(param));
		}
		map.put("app_list", apps);

		return AjaxMap.success(map);
	}

	/**
	 * 把map转成url参数拼接
	 */
	private String asUrlParams(Map<String, String> source) {
		Iterator<String> it = source.keySet().iterator();
		StringBuilder paramStr = new StringBuilder();
		while (it.hasNext()) {
			String key = it.next();
			String value = source.get(key);
			if (StringUtils.isBlank(value)) {
				continue;
			}
			try {
				// URL 编码
				value = URLEncoder.encode(value, "utf-8");
			} catch (UnsupportedEncodingException e) {
				// do nothing
			}
			paramStr.append("&").append(key).append("=").append(value);
		}
		// 去掉第一个&
		return paramStr.substring(1);
	}

	/**
	 * @explain 查询对象 <swagger GET请求>
	 * @param 对象参数：id
	 * @return JsonResult
	 * @author LuZhongren
	 * @time 2022年1月27日
	 */
	@PostMapping("/getMenuInfo")
	@ApiOperation(value = "获取菜单管理对象", notes = "作者：LuZhongren")
	public AjaxResult<SysMenu> getMenuInfo(@RequestBody Map<String, Object> map) {
		if(map==null) return AjaxResult.failed(MessageUtils.message("search.not.exist"));
		Long menu_id=Long.parseLong(map.get("menu_id").toString());
		SysMenu sysMenu = sysMenuService.getById(menu_id);
		if (null != sysMenu) {
			return AjaxResult.success(sysMenu);
		} else {
			return AjaxResult.failed(MessageUtils.message("search.not.exist"));
		}

	}

	/**
	 * @explain 删除对象
	 * @param 对象参数：id
	 * @return JsonResult
	 * @author LuZhongren
	 * @time 2022年1月27日
	 */
	@PostMapping("/deleteMenu")
	@ApiOperation(value = "删除", notes = "作者：LuZhongren")
	public AjaxResult<SysMenu> deleteMenu(@RequestBody Map<String, Object> map) {
		if(map==null) return AjaxResult.failed(MessageUtils.message("search.not.exist"));
		Long menu_id=Long.parseLong(map.get("menu_id").toString());
		SysMenu sysMenu = sysMenuService.getById(menu_id);
		if (null != sysMenu) {
			boolean rsg = sysMenuService.removeById(menu_id);
			if (rsg) {
				sysFieldService.remove(new QueryWrapper<SysField>().eq("menu_id", menu_id));
				sysActionService.remove(new QueryWrapper<SysAction>().eq("menu_id", menu_id));
				// Remove field and action
				return AjaxResult.success(MessageUtils.message("delete.success"));
			} else {
				return AjaxResult.failed(MessageUtils.message("delete.fail"));
			}
		} else {
			return AjaxResult.failed(MessageUtils.message("delete.not.exist"));
		}

	}
	
	/**
	 * @explain 把字段标题插入到多语言管理
	 * @param 对象参数：id
	 * @return JsonResult
	 * @author LuZhongren
	 * @time 2022年1月27日
	 */
	@PostMapping("/createLanguage")
	@ApiOperation(value = "多语言配置", notes = "作者：LuZhongren")
	public AjaxResult<SysMenu> createLanguage(@RequestBody Map<String, Object> map) {
		if(map==null) return AjaxResult.failed(MessageUtils.message("search.not.exist"));
		Long menu_id=Long.parseLong(map.get("menu_id").toString());
		
		SysMenu sysMenu = sysMenuService.getById(menu_id);
		List<SysField> sysFields=sysFieldService.list(new QueryWrapper<SysField>().eq("menu_id", menu_id));
		List<SysAction> sysActions=sysActionService.list(new QueryWrapper<SysAction>().eq("menu_id", menu_id));
		
		I118 entity=i118Service.getOne(new QueryWrapper<I118>().eq("controller", "menu").eq("message_id", "menu."+sysMenu.getController_name()));
		if(entity==null) entity=new I118();
		entity.setController("menu");
		entity.setMessage_id("menu."+sysMenu.getController_name());
		entity.setType(1);
		entity.setUse_way(3);
		entity.setName(sysMenu.getTitle());
		entity.setLanguage_zh(sysMenu.getTitle());
		entity.setOriginal_id(menu_id);
		entity.setLanguage_en(sysMenu.getController_name());
		entity.insertOrUpdate();
		
		for (SysAction sysAction : sysActions) {
			Integer groupButton=sysAction.getGroup_button_status();
			Integer listButton=sysAction.getList_button_status();
			if(groupButton==null) groupButton=0;
			if(listButton==null) listButton=0;
			if(groupButton==1 || listButton==1) {
				I118 entityAction=i118Service.getOne(new QueryWrapper<I118>().eq("controller", "action").eq("message_id", "action."+sysAction.getAction_name()));
				if(entityAction==null) entityAction=new I118();
				entityAction.setController("action");
				entityAction.setMessage_id("action."+sysAction.getAction_name());
				entityAction.setType(1);
				entityAction.setUse_way(3);
				entityAction.setName(sysAction.getName());
				entityAction.setLanguage_zh(sysAction.getName());
				//entityAction.setOrigial_id(sysAction.getId());
				entityAction.setLanguage_en(sysAction.getAction_name());
				entityAction.insertOrUpdate();
			}
	
			
		}
		for(SysField sysField:sysFields) {
			//if(sysField.getField().equals(sysMenu.getPk())) continue;
			String table=sysField.getBelong_table();
			String message_id="field."+sysMenu.getController_name()+"_"+sysField.getField();
			if(StringUtils.hasText(table))
				message_id="field."+sysMenu.getController_name()+"_"+ table.replace(tablePrefix,"" )+"_"+ sysField.getField();
			
			I118 entityField=i118Service.getOne(new QueryWrapper<I118>().eq("controller", "field").eq("message_id", message_id));
			if(entityField==null) entityField=new I118();
			entityField.setController("field");	
			entityField.setMessage_id(message_id);
			entityField.setType(1);
			entityField.setUse_way(3);
			entityField.setName(sysField.getTitle());
			entityField.setLanguage_zh(sysField.getTitle());
			entityField.setOriginal_id(sysField.getId());
			entityField.setLanguage_en(StringUtils.firstCharToUppercase(sysField.getField()));
			entityField.insertOrUpdate();
		}
		List<SysMenu> menuList=sysMenuService.list();
		for (SysMenu sysMenu2 : menuList) {
			I118 entityMenu=i118Service.getOne(new QueryWrapper<I118>().eq("controller", "menu").eq("message_id", "menu."+sysMenu2.getController_name()));
			if(entityMenu !=null) continue;
			entityMenu=new I118();
			entityMenu.setController("menu");
			entityMenu.setMessage_id("menu."+sysMenu2.getController_name());
			entityMenu.setType(1);
			entityMenu.setUse_way(3);
			entityMenu.setName(sysMenu2.getTitle());
			entityMenu.setLanguage_zh(sysMenu2.getTitle());
			entityMenu.setOriginal_id(sysMenu2.getMenu_id());
			entityMenu.setLanguage_en(sysMenu2.getController_name());
			entityMenu.insertOrUpdate();
		}
		
	    
	
		return AjaxResult.success(MessageUtils.message("insert.success"));
			

	}

	/**
	 * 首字母转换成大写
	 * 
	 * @param controllerName
	 * @return
	 */
	private String setControllerName(String controllerName) {
		if (controllerName.indexOf('/') > 0) {
			String[] divides = StringUtils.split(controllerName, '/');
			for (int i = 0; i < divides.length; i++) {
				divides[i] = StringUtils.firstCharToUppercase(divides[i]);
			}
			controllerName = StringUtils.join(divides, '/');
		} else {
			controllerName = StringUtils.firstCharToUppercase(controllerName);
		}

		return StringUtils.replace(controllerName, "_", "");
	}

	/**
	 * @explain 添加
	 * @param 对象参数：SysMenu
	 * @return Boolean
	 * @author LuZhongren
	 * @time 2022年1月27日
	 */
	@PostMapping("/createMenu")
	@ApiOperation(value = "添加菜单", notes = "作者：LuZhongren")
	public AjaxResult<SysMenu> createMenu(@RequestBody SysMenu entity) {

		if (null != entity) {
			entity.setController_name(this.setControllerName(entity.getController_name()));
			entity.setModule(WonderConfig.getAppFolder());
			boolean rsg = sysMenuService.save(entity);
			if (rsg) {
				Long menu_id = entity.getMenu_id();
				if (menu_id > 0 && entity.getTable_name() != null && entity.getPk() != null
						&& entity.getCreate_code() > 0 && entity.getStatus() > 0 && entity.getPage_type() != null) {
					// Create the default action
					for (Map<String, Object> item : Parameters.actionList()) {
						if (item.get("default_create") != null && entity.getPage_type() == 1) {
							int actionType = (Integer) item.get("type");
							boolean defaultCreate = (boolean) item.get("default_create");
							if (actionType != 10 && actionType != 11 && defaultCreate) {
								SysAction action = new SysAction();
								try {
									
									 BeanUtils.copyProperties2Bean(item, action);  //(field, item);
									//BeanUtils(action, item);
									action.setMenu_id(menu_id);
									sysActionService.save(action);
								} catch (Exception e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							}

						}
					}
					// Create the default field PK
					for (Map<String, Object> item : Parameters.defaultFields()) {
						if (item.get("primary") != null && entity.getPage_type() == 1) {
							SysField field = new SysField();
							try {
								BeanUtils.copyProperties2Bean(item, field);   //(field, item);
								field.setField(entity.getPk());
								field.setMenu_id(menu_id);
								field.setPost_status(0);
								field.setSearch_type(0);
								sysFieldService.save(field);

							} catch (Exception e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}

						}

					}
					// Create the index list page
					if (entity.getPage_type() == 2) {
						SysAction action = new SysAction();
						action.setMenu_id(menu_id);
						action.setName(entity.getTitle());
						action.setAction_name("index");
						action.setType(14);
						sysActionService.save(action);
					}
				}
				SysMenu sysMenu=new SysMenu();
				sysMenu.setSortid(menu_id.intValue());
				sysMenu.setMenu_id(menu_id);
				sysMenu.updateById();

				return AjaxResult.success(MessageUtils.message("insert.success"));
			} else {
				return AjaxResult.failed(MessageUtils.message("insert.fail"));
			}
		} else {
			return AjaxResult.failed(MessageUtils.message("insert.parameter.error"));
		}
	}

	/**
	 * @explain 修改
	 * @param 对象参数：SysMenu
	 * @return Boolean
	 * @author LuZhongren
	 * @time 2022年1月27日
	 */
	@PostMapping("/updateMenu")
	@ApiOperation(value = "修改菜单", notes = "作者：LuZhongren")
	public AjaxResult<SysMenu> updateMenu(@RequestBody SysMenu entity) {
		if (null != entity) {
			entity.setController_name(this.setControllerName(entity.getController_name()));

			boolean rsg = sysMenuService.updateById(entity);
			if (rsg) {
				if (entity.getPage_type() == 2) {
					sysActionService
							.remove(new QueryWrapper<SysAction>().eq("menu_id", entity.getMenu_id()).ne("type", 14));
					long count = sysActionService
							.count(new QueryWrapper<SysAction>().eq("menu_id", entity.getMenu_id()).eq("type", 14));
					if (count <= 0) {
						SysAction action = new SysAction();
						     action.setMenu_id(entity.getMenu_id());
						     action.setName(entity.getTitle());
						     action.setAction_name("index");
						     action.setType(14);
						sysActionService.save(action);
					}
				}
				return AjaxResult.success(MessageUtils.message("update.success"));

			} else {
				return AjaxResult.failed(MessageUtils.message("update.fail"));
			}
		} else {
			return AjaxResult.failed(MessageUtils.message("update.not.exist"));
		}
	}

	/**
	 * @explain 修改
	 * @param 对象参数：SysMenu
	 * @return Boolean
	 * @author LuZhongren
	 * @time 2022年1月27日
	 */
	@PostMapping("/updateMenuExt")
	@ApiOperation(value = "修改菜单单个字段", notes = "作者：LuZhongren")
	public AjaxResult<SysMenu> updateMenuExt(@RequestBody SysMenu entity) {
		if (null != entity) {
			boolean rsg = sysMenuService.updateEx(entity) > 0 ? true : false;
			if (rsg) {
				return AjaxResult.success(MessageUtils.message("update.success"));

			} else {
				return AjaxResult.failed(MessageUtils.message("update.fail"));
			}
		} else {
			return AjaxResult.failed(MessageUtils.message("update.not.exist"));
		}
	}
	
	
	@Autowired
	GeneratorService generatorService;
	
	@Autowired
	RestTemplate restTemplate;
	
	/**
	 * @explain Generate the source code
	 * @param 对象参数：SysMenu
	 * @return Boolean
	 * @author LuZhongren
	 * @time 2022年1月27日
	 */
	@PostMapping("/create")
	@ApiOperation(value = "Generate the source code", notes = "作者：LuZhongren")
	public AjaxResult<Map<String, String>> createCode(@RequestBody Map<String, Object> map) {
		if(map==null) return AjaxResult.failed(MessageUtils.message("search.not.exist"));
		Long menu_id=Long.parseLong(map.get("menu_id").toString());
		
		generatorService.Initialize(menu_id);
		ModuleInfo dataModel=generatorService.getDataModel();
		AjaxResult<Map<String, String>> codeList=httpCode(dataModel, "code/remoteCode");
		if(codeList!=null && codeList.getStatus()!=ExceptionCodeEnum.ERROR.getCode()) {
			generatorService.writeCode(codeList.getData(),dataModel);
			return AjaxResult.success();
		}
		

	    return AjaxResult.failed();
		
	}
	
	/**
	 * @explain Get the preview source code
	 * @param 对象参数：SysMenu
	 * @return Boolean
	 * @author LuZhongren
	 * @time 2022年1月27日
	 */
	@PostMapping("/createPreview")
	@ApiOperation(value = "Get the preview source code", notes = "作者：LuZhongren")
	public AjaxResult<Map<String, String>> createPreview(@RequestBody Map<String, Object> map) {
		if(map==null) return AjaxResult.failed(MessageUtils.message("search.not.exist"));
		Long menu_id=Long.parseLong(map.get("menu_id").toString());
		
		generatorService.Initialize(menu_id);
		ModuleInfo dataModel=generatorService.getDataModel();

		AjaxResult<Map<String, String>> json=httpCode(dataModel, "code/remotePreview");
		if(json.getStatus()==ExceptionCodeEnum.SUCCESS.getCode()) {
			return AjaxResult.success(json.getData());
		}

	    return AjaxResult.failed();
	}
	
	/**
	 * @explain Get the preview source code
	 * @param 对象参数：SysMenu
	 * @return Boolean
	 * @author LuZhongren
	 * @time 2022年1月27日
	 */
	@PostMapping("/createDownload")
	@ApiOperation(value = "Download the source code", notes = "作者：LuZhongren")
	public void createDownload(HttpServletResponse response,@RequestBody Map<String, Object> map) throws IOException {
		if(map==null) return ;
		Long menu_id=Long.parseLong(map.get("menu_id").toString());
		generatorService.Initialize(menu_id);
		ModuleInfo dataModel=generatorService.getDataModel();
		AjaxResult<Map<String, String>> codeList=httpCode(dataModel, "code/remoteCode");
		if(codeList!=null && codeList.getStatus()!=ExceptionCodeEnum.ERROR.getCode()) {
			byte[] data = generatorService.downloadCode(codeList.getData(), dataModel);
			genCode(response, data);
		}
	}
	
	
	 /**
     * 生成zip文件
     */
    private void genCode(HttpServletResponse response, byte[] data) throws IOException
    {
        response.reset();
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment; filename=\"generated.zip\"");
        response.addHeader("Content-Length", "" + data.length);
        response.setContentType("application/octet-stream; charset=UTF-8");
        IOUtils.write(data, response.getOutputStream());
    }
	
	

	
	


	private AjaxResult<Map<String, String>> httpCode(ModuleInfo dataModel,String api) {
		 //1、构建body参数
		
        //2、添加请求头
        HttpHeaders httpHeaders = new HttpHeaders();
        MediaType type=MediaType.parseMediaType("application/json;charset=UTF-8");
        httpHeaders.setContentType(type);

        //3、组装请求头和参数
        HttpEntity<ModuleInfo> objectHttpEntity = new HttpEntity<>(dataModel,httpHeaders);
        AjaxResult<Map<String, String>> returnClass=AjaxResult.success();   
        AjaxResult<Map<String, String>> result=restTemplate.postForEntity(toolsUrl+api, objectHttpEntity, returnClass.getClass()).getBody();
        if(result==null || result.getStatus()==ExceptionCodeEnum.ERROR.getCode()) return AjaxResult.failed();
        return result;        
//        JSONObject json = restTemplate.postForEntity(toolsUrl+api, objectHttpEntity, JSONObject.class).getBody();
//        log.info("json:{}"+json.toJSONString());
//        return json;

//        //4、发起post请求
//        ResponseEntity<AjaxResult<Map<String, OBject>>> stringResponseEntity = null;
//        try {
//            stringResponseEntity = restTemplate.postForEntity(toolsUrl+api, objectHttpEntity, String.class);
//            log.info("ResponseEntity----"+stringResponseEntity);
//        } catch (RestClientException e) {
//            e.printStackTrace();
//        }
//
//        //5、获取http状态码
//        int statusCodeValue = stringResponseEntity.getStatusCodeValue();
//        log.info("httpCode-----"+statusCodeValue);
//
//        //6、获取返回体
//        String body = stringResponseEntity.getBody();
//        log.info("body-----"+body);
//
//        //7、映射实体类
//        Wrapper wrapper = JSONObject.parseObject(body, Wrapper.class);
//        String data = wrapper.getData();
//        log.info("data-----"+data);
	}

}